package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Movement;
import com.itheima.domain.vo.CommentVo;
import com.itheima.domain.vo.MovementVo;
import com.itheima.domain.vo.PageBeanVo;
import com.itheima.domain.vo.UserCommentVo;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.MovementService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.DateFormatUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class MovementManager {

    @Autowired
    private OssTemplate ossTemplate;
    @Reference
    private MovementService movementService;
    @Reference
    private UserInfoService userInfoService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Reference
    private CommentService commentService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MQMovementManager mqMovementManager;
    /**
     * 保存动态
     */
    public void saveMovement(Movement movement, MultipartFile[] imageContent) throws IOException {

        //上传文件地址的集合数据
        List<String> medias = new ArrayList<>();
        //1.将图片存储到oss平台
        if(imageContent != null && imageContent.length>0){//非空校验
            for (MultipartFile multipartFile : imageContent) {
                String path = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
                medias.add("https://"+path);
            }
        }

        //2.获得userId(当前登录人id)
        Long id = UserHolder.getId();
        //3.初始化 movement 对象  (补充部分数据)
        movement.setUserId( id );//赋值用户id
        //movement.setPid(0L); //TODO 大数据推荐id 暂时写死
        movement.setMedias(medias);//图片信息数据
        movement.setState(0);//TODO 后续华为云进行数据审核 暂时写死
        //movement.setCreated();//不在这些 在提供者中书写(时间应该保存的时候动态的数据)
        movement.setSeeType(1);//公开都能看见 默认数据 本项目没有使用
        //4.调用service保存动态即可
        ObjectId movementId = movementService.saveMovement(movement);

        //5.通知华为云审核  传递了动态的id  null.方法
        rocketMQTemplate.convertAndSend("tanhua-huawei" , movementId.toHexString());
    }
    /**
     * 查询我的个人动态或者以后查询别人的动态
     */
    public PageBeanVo findMyMovement(Integer pageNumber, Integer pageSize, Long userId) {
        //1.分页查询个人的动态信息
        PageBeanVo pageBeanVo = movementService.findMyMovement(pageNumber , pageSize , userId);
        System.out.println(pageBeanVo);


        //2.根据所得到的动态 , 需要查询到个人的信息
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        //定义返回的数据集合
        List<MovementVo> movementVos = new ArrayList<>();

        if(CollectionUtil.isNotEmpty(items)){
            for (Movement movement : items) {//遍历动态
                Long movementUserId = movement.getUserId();//发布动态这个人的id
                UserInfo userInfo = userInfoService.findById(movementUserId);//查询的个人信息
                //3.将动态 和 个人信息封装一个新的vo对象
                MovementVo movementVo = new MovementVo();
                //数据的转换  个人-> vo
                movementVo.setUserInfo(userInfo);
                //数据的转换  动态-> vo
                movementVo.setMovement(movement);
                //将封装好的数据 给到集合
                movementVos.add(movementVo);
            }
        }
        //4.将数据返回
        pageBeanVo.setItems(movementVos);


        return pageBeanVo;
    }
    /**
     * 查询好友动态
     */
    public PageBeanVo findFriendMovements(Integer pageNumber, Integer pageSize) {
        //1.分页查询个人的动态信息
        PageBeanVo pageBeanVo = movementService.findFriendMovements(pageNumber , pageSize , UserHolder.getId());
        System.out.println(pageBeanVo);



        //2.根据所得到的动态 , 需要查询到个人的信息
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        //定义返回的数据集合
        List<MovementVo> movementVos = new ArrayList<>();

        if(CollectionUtil.isNotEmpty(items)){
            for (Movement movement : items) {//遍历动态
                Long movementUserId = movement.getUserId();//发布动态这个人的id
                UserInfo userInfo = userInfoService.findById(movementUserId);//查询的个人信息
                //3.将动态 和 个人信息封装一个新的vo对象
                MovementVo movementVo = new MovementVo();
                //数据的转换  个人-> vo
                movementVo.setUserInfo(userInfo);
                //数据的转换  动态-> vo
                movementVo.setMovement(movement);

                //判断 该动态是否被点过赞  xx对 哪个 动态进行了点赞 缓存是否有这条数据
                String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), movement.getId());
                if(stringRedisTemplate.hasKey(key)){
                    movementVo.setHasLiked(1);//1表示已经点过赞
                }

                //将封装好的数据 给到集合
                movementVos.add(movementVo);
            }
        }
        //4.将数据返回
        pageBeanVo.setItems(movementVos);
        return pageBeanVo;
    }

    /**
     * 查询推荐动态
     */
    public PageBeanVo findRecommendMovement(Integer pageNumber, Integer pageSize) {
        //1.分页查询推荐的动态信息
        PageBeanVo pageBeanVo = movementService.findRecommendMovement(pageNumber , pageSize , UserHolder.getId());
        //3.拿出原来的数据
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        List<MovementVo> movementVoList =  new ArrayList();
        //4.构造页面返回数据
        if(CollectionUtil.isNotEmpty(items)){
            for (Movement movement : items) {
                Long movementUserId = movement.getUserId();//发布动态这个人的id
                UserInfo userInfo = userInfoService.findById(movementUserId);//查询的个人信息
                //3.将动态 和 个人信息封装一个新的vo对象
                MovementVo movementVo = new MovementVo();
                //数据的转换  个人-> vo
                movementVo.setUserInfo(userInfo);
                //数据的转换  动态-> vo
                movementVo.setMovement(movement);
                //判断 该动态是否被点过赞  xx对 哪个 动态进行了点赞 缓存是否有这条数据
                String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), movement.getId());
                if(stringRedisTemplate.hasKey(key)){
                    movementVo.setHasLiked(1);//1表示已经点过赞
                }

                //将封装好的数据 给到集合
                movementVoList.add(movementVo);
            }
        }


        pageBeanVo.setItems(movementVoList);
        //2.返回
        return pageBeanVo;
    }



    /**
     * 点赞
     */
    public Integer saveMovementLike(String movementId) {
        //1.构建comment对象
        Comment comment = new Comment();
        comment.setPublishId( new ObjectId(movementId));//动态id
        comment.setCommentType(1);//点赞
        comment.setUserId( UserHolder.getId() );//当前登录人的id 操作人
        //2.保存对象
        Integer count = commentService.saveMovementComment(comment);
        //4.将数据存入缓存redis中   xx对 哪个 动态进行了点赞  userId , 动态的id    "movement_like:用户id_动态id"
        //stringRedisTemplate.opsForValue().set(  "movement_like:"+userId+"_"+动态id+"", "1");   "movement_like:{}_{}";
        //StrUtil.format 工具类 作用: 将参数直接封装到字符串中 好处在于不需要拼接字符串 {} 表示占位符
        String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), movementId);
        stringRedisTemplate.opsForValue().set(key, "1");
        //3.返回数据
        //发送MQ操作
        mqMovementManager.sendMsg(movementId ,MQMovementManager.MOVEMENT_LIKE );
        return count;
    }

    /**
     * 取消点赞
     */
    public Integer deleteMovementLike(String movementId) {
        //1.构建comment对象
        Comment comment = new Comment();
        comment.setPublishId( new ObjectId(movementId));//动态id
        comment.setCommentType(1);//点赞
        comment.setUserId( UserHolder.getId() );//当前登录人的id 操作人
        //2.保存对象
        Integer count = commentService.deleteMovementComment(comment);
        //4.将数据从缓存中移除
        String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), movementId);
        stringRedisTemplate.delete(key);
        //3.返回数据
        //发送MQ操作
        mqMovementManager.sendMsg(movementId ,MQMovementManager.MOVEMENT_DISLIKE );
        return count;
    }

    /**
     * 单条动态
     */
    public MovementVo findMovementById(String movementId) {
        //1.根据id查询动态对象
        Movement movement = movementService.findMovementById(movementId);

        //2.根据movement 查询用户信息
        UserInfo userInfo = userInfoService.findById(movement.getUserId());
        //3.创建对象
        MovementVo vo= new MovementVo();

        //4.赋值数据
        vo.setUserInfo(userInfo);
        vo.setMovement( movement );

        //发送MQ操作
        mqMovementManager.sendMsg(movementId ,MQMovementManager.MOVEMENT_BROWSE );
        return vo;
    }

    /**
     * 查询动态的评论
     */
    public PageBeanVo findMovementComment(Integer pageNumber, Integer pageSize, String movementId) {
        //1.分页查询动态评论
        PageBeanVo pageBeanVo = commentService.findMovementComment(movementId, pageNumber, pageSize);
        //2.根据动态的评论查询个人信息
        List<Comment> items = (List<Comment>) pageBeanVo.getItems();
        List<CommentVo> commentVoList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(items)){
            for (Comment comment : items) {
                //3.封装CommentVo -> 这是一个集合
                //查询个人信息
                UserInfo userInfo = userInfoService.findById(comment.getUserId());

                //创建对象
                CommentVo vo = new CommentVo();
                BeanUtil.copyProperties(userInfo , vo);
                BeanUtil.copyProperties(comment , vo);

                //处理时间
                vo.setCreateDate(new SimpleDateFormat("yyyy-MM-dd").format( new Date(comment.getCreated())));
                //存入集合
                commentVoList.add(vo);
            }
        }

        pageBeanVo.setItems(commentVoList);
        return pageBeanVo;
    }

    /**
     * 保存评论
     */
    public Map saveMovementComment(String movementId, String content) {
        //1.构建comment对象
        Comment comment = new Comment();
        comment.setCommentType(2);//评论
        comment.setUserId(UserHolder.getId());//操作人
        comment.setContent(content);//赋值评论内容
        comment.setPublishId( new ObjectId(movementId));//赋值动态id
        //2.直接保存即可
        commentService.saveMovementComment(comment);

        //发送MQ操作
        mqMovementManager.sendMsg(movementId ,MQMovementManager.MOVEMENT_COMMENT );
        return null;
    }

    /**
     * 根据传入的类型 查询统计 喜欢 评论 点赞 列表
     */
    public PageBeanVo findCommentByCommentType(Integer pageNumber, Integer pageSize, int commentType) {
        //1.根据传入的类型 查询统计 喜欢 评论 点赞 列表
        PageBeanVo pageBeanVo =  commentService.findCommentByCommentType(pageNumber , pageSize , commentType , UserHolder.getId());

        List<Comment> items = (List<Comment>) pageBeanVo.getItems();

        List<UserCommentVo> list = new ArrayList<>();
        //3.构造返回的vo
        if(CollectionUtil.isNotEmpty(items)){
            for (Comment comment : items) {
                //根据评论查询用户的数据
                UserInfo userInfo = userInfoService.findById(comment.getUserId());
                //创建对象
                UserCommentVo vo = new UserCommentVo();
                vo.setNickname( userInfo.getNickname() ); // 昵称
                vo.setAvatar( userInfo.getAvatar() ); //头像
                vo.setId( comment.getId().toHexString() ); //给评论的id
                vo.setCreateDate( new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( new Date(comment.getCreated()) ) );
                //添加到集合
                list.add(vo);
            }
        }

        pageBeanVo.setItems(list);
        //2.返回数据
        return pageBeanVo;
    }



    /*public PageBeanVo findMyMovement(Integer pageNumber, Integer pageSize, Long userId) {
        //1.分页查询个人的动态信息
        PageBeanVo pageBeanVo = movementService.findMyMovement(pageNumber , pageSize , userId);
        System.out.println(pageBeanVo);


        //2.根据所得到的动态 , 需要查询到个人的信息
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        //定义返回的数据集合
        List<MovementVo> movementVos = new ArrayList<>();

        if(CollectionUtil.isNotEmpty(items)){
            for (Movement movement : items) {//遍历动态
                Long movementUserId = movement.getUserId();//发布动态这个人的id
                UserInfo userInfo = userInfoService.findById(movementUserId);//查询的个人信息
                //3.将动态 和 个人信息封装一个新的vo对象
                MovementVo movementVo = new MovementVo();

                //数据的转换  个人-> vo
                BeanUtil.copyProperties(userInfo ,movementVo );
                movementVo.setUserId( userInfo.getId() );  // 赋值id信息
                if(userInfo.getTags() != null){ //赋值标签信息
                    movementVo.setTags( userInfo.getTags().split(",") );
                }


                //数据的转换  动态-> vo
                BeanUtil.copyProperties(movement ,movementVo );
                //图片需要处理
                if(CollectionUtil.isNotEmpty(movement.getMedias())){
                    //将集合转换成数组
                    movementVo.setImageContent( movement.getMedias().toArray(new String[]{}) );
                }

                //距离写死
                movementVo.setDistance("5公里");
                //发布时间
                String formatDate = DateFormatUtil.format(new Date(movement.getCreated()));
                movementVo.setCreateDate( formatDate  );
                //将封装好的数据 给到集合
                movementVos.add(movementVo);
            }
        }
        //4.将数据返回
        pageBeanVo.setItems(movementVos);
        return pageBeanVo;
    }*/
}
